/**  
* @Title: TaobaoServiceImpl.java 
* @Description:
* @Copyright: Copyright (c) 2018
* @Company:http://www.sinocon.cn
* @author: Su.Yuanlin  
* @date 2019年4月11日  
* @QQ 314078331  
* @Like 流水落花春去也，天上人间
*/
package com.mtons.mblog.modules.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import com.mtons.mblog.base.utils.BeanMapUtils;
import com.mtons.mblog.modules.data.AnalysisVO;
import com.mtons.mblog.modules.data.SalesVo;
import com.mtons.mblog.modules.entity.Product;
import com.mtons.mblog.modules.entity.Sales;
import com.mtons.mblog.modules.repository.ProductRepository;
import com.mtons.mblog.modules.repository.SalesRepository;
import com.mtons.mblog.modules.service.TaobaoService;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

/**
 * @Title: TaobaoServiceImpl
 * @Description:
 * @author:Su.Yuanlin
 * @date 2019年4月11日
 */
@Service
public class TaobaoServiceImpl implements TaobaoService {
	@Autowired
	private ProductRepository productRepository;
	@Autowired
	private SalesRepository salesRepository;
	@Autowired
	private JdbcTemplate jdbcTemplate;

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: saveOrUpdateProduct</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param p
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.TaobaoService#saveOrUpdateProduct(com.
	 * mtons.mblog.modules.entity.Product)
	 * 
	 */
	@Override
	public int saveOrUpdateProduct(Product p) {
		try {
			if (StrUtil.isBlank(p.getProductId())) {
				p.setProductId(UUID.randomUUID().toString());
			}
			this.productRepository.save(p);
		} catch (Exception e) {
			e.printStackTrace();
			return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
		}

		return HttpServletResponse.SC_OK;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: addProduct</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param listProduct
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.TaobaoService#addProduct(java.util.List)
	 * 
	 */
	@Override
	public int addProduct(List<Product> listProduct) {
		try {
			this.productRepository.saveAll(listProduct);
		} catch (Exception e) {
			e.printStackTrace();
			return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
		}
		return HttpServletResponse.SC_OK;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: delProduct</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param id
	 * 
	 * @return
	 * 
	 * @see com.mtons.mblog.modules.service.TaobaoService#delProduct(java.lang.
	 * String)
	 * 
	 */
	@Override
	public int delProduct(String id) {
		try {
			this.productRepository.deleteById(id);
		} catch (Exception e) {
			e.printStackTrace();
			return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
		}
		return HttpServletResponse.SC_OK;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: getProductAll</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @return
	 * 
	 * @see com.mtons.mblog.modules.service.TaobaoService#getProductAll()
	 * 
	 */
	@Override
	public List<Product> getProductAll() {
		return this.productRepository.findAll();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: getProductByProductName</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param productName
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.TaobaoService#getProductByProductName(
	 * java.lang.String)
	 * 
	 */
	@Override
	public Page<Product> getProductByProductName(Pageable pageable, String productName) {
		return this.productRepository.findAll(productWhere(productName), pageable);
	}

	@SuppressWarnings("serial")
	private Specification<Product> productWhere(String productName) {
		return new Specification<Product>() {
			@Override
			public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<>();

				if (StrUtil.isNotBlank(productName)) {
					Predicate p = criteriaBuilder.like(root.get("productName"), "%" + productName + "%");
					predicates.add(p);
				}

				return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
			}
		};
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: getProductById</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param id
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.TaobaoService#getProductById(java.lang.
	 * String)
	 * 
	 */
	@Override
	public Product getProductById(String id) {
		Optional<Product> po = this.productRepository.findById(id);
		if (po.isPresent()) {
			return po.get();
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: saveOrUpdateSales</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param sales
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.TaobaoService#saveOrUpdateSales(com.mtons
	 * .mblog.modules.entity.Sales)
	 * 
	 */
	@Override
	public int saveOrUpdateSales(Sales sales) {
		try {
			List<Sales> exitsList = this.salesRepository
					.findAll(salesWhere("2018-03-01", DateUtil.today(), "", sales.getTaobaoOrder(), ""));
			if (exitsList.isEmpty()) {
				sales.setSalesId(UUID.randomUUID().toString());
				this.salesRepository.save(sales);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
		}
		return HttpServletResponse.SC_OK;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: addSales</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param list
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.TaobaoService#addSales(java.util.List)
	 * 
	 */
	@Override
	public int addSales(List<Sales> list) {
		try {
			this.salesRepository.saveAll(list);
		} catch (Exception e) {
			e.printStackTrace();
			return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
		}
		return HttpServletResponse.SC_OK;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: getSalesById</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param id
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.TaobaoService#getSalesById(java.lang.
	 * String)
	 * 
	 */
	@Override
	public Sales getSalesById(String id) {

		return this.salesRepository.findById(id).get();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: getSalesByTime</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param pageable
	 * 
	 * @param time
	 * 
	 * @return
	 * 
	 * @see com.mtons.mblog.modules.service.TaobaoService#getSalesByTime(org.
	 * springframework.data.domain.Pageable, java.lang.String)
	 * 
	 */
	@Override
	public Page<SalesVo> getSalesByTime(Pageable pageable, String begin, String end, String productId, String kw,
			String isNatural) {
		Page<Sales> page = this.salesRepository.findAll(salesWhere(begin, end, productId, kw, isNatural), pageable);
		List<SalesVo> rets = new ArrayList<>();
		page.getContent().stream().forEach(sl -> {
			SalesVo vo = BeanMapUtils.copy(sl);
			vo.setProduct(this.productRepository.findById(sl.getProductId()).get());
			rets.add(vo);
		});
		return new PageImpl<>(rets, pageable, page.getTotalElements());
	}

	@SuppressWarnings("serial")
	private Specification<Sales> salesWhere(String beginTime, String endTime, String productId, String kw,
			String isNatural) {
		return new Specification<Sales>() {
			@Override
			public Predicate toPredicate(Root<Sales> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<>();

				Date date1 = DateUtil.parse(beginTime);

				Date date2 = DateUtil.parse(endTime);

				Predicate p = criteriaBuilder.between(root.get("buyTime"), date1, date2);
				if (StrUtil.isNotBlank(productId)) {
					p = criteriaBuilder.and(p, criteriaBuilder.equal(root.get("productId"), productId));
				}
				if (StrUtil.isNotBlank(isNatural)) {
					p = criteriaBuilder.and(p, criteriaBuilder.equal(root.get("isNatural"), isNatural));
				}

				predicates.add(p);

				if (StrUtil.isNotBlank(kw)) {
					Predicate p2 = criteriaBuilder.or(criteriaBuilder.like(root.get("buyer"), "%" + kw + "%"));
					p2 = criteriaBuilder.or(p2, criteriaBuilder.like(root.get("wangwangID"), "%" + kw + "%"));
					p2 = criteriaBuilder.or(p2, criteriaBuilder.like(root.get("nickName"), "%" + kw + "%"));
					p2 = criteriaBuilder.or(p2, criteriaBuilder.like(root.get("taobaoOrder"), "%" + kw + "%"));
					predicates.add(p2);
				}

				return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
			}
		};
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: getSalesByTaobaoOrder</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param order
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.TaobaoService#getSalesByTaobaoOrder(java.
	 * lang.String)
	 * 
	 */
	@Override
	public Sales getSalesByTaobaoOrder(String order) {
		List<Sales> exitsList = this.salesRepository.findAll(salesWhere("2018-03-01", DateUtil.today(), "", order, ""));
		if (ObjectUtil.isNotNull(exitsList) && !exitsList.isEmpty())
			return exitsList.get(0);
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: checkTaobaoOrderExist</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @param order
	 * 
	 * @return
	 * 
	 * @see
	 * com.mtons.mblog.modules.service.TaobaoService#checkTaobaoOrderExist(java.
	 * lang.String)
	 * 
	 */
	@Override
	public boolean checkTaobaoOrderExist(String order) {
		Sales salesByTaobaoOrder = getSalesByTaobaoOrder(order);
		return ObjectUtil.isNotNull(salesByTaobaoOrder);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Title: getAnalysisData</p>
	 * 
	 * <p>Description: </p>
	 * 
	 * @return
	 * 
	 * @see com.mtons.mblog.modules.service.TaobaoService#getAnalysisData()
	 * 
	 */
	@Override
	public AnalysisVO getAnalysisData(String productId, String isNatural, String begin, String end, String status,
			String kw) {
		List<String> params = new ArrayList<>();
		StringBuffer bufferSql = new StringBuffer();
		String columns = "sum(a.commission_Fee) commissionFeeCnt ,sum(b.buying_price) principalFeeCnt,sum(a.buy_cnt) sellNumCnt,sum(a.buy_price) sellFeeCnt,sum(a.express_fee) expressFeeCnt";
		bufferSql.append("SELECT ").append(columns).append(" from mto_sales a ");
		bufferSql.append("LEFT JOIN mto_product b ON a.product_id = b.product_id WHERE 1=1 ");
		if (StrUtil.isNotBlank(productId)) {
			params.add(productId);
			bufferSql.append(" AND a.product_id= ? ");
		}

		if (StrUtil.isNotBlank(isNatural)) {
			params.add(isNatural);
			bufferSql.append(" AND a.is_natural= ? ");
		}

		if (StrUtil.isNotBlank(begin)) {
			params.add(begin);
			params.add(end);
			bufferSql.append("and (a.buy_time BETWEEN ? and ? )");
		}

		if (StrUtil.isNotBlank(status)) {
			params.add(status);
			bufferSql.append(" AND a.status = ? ");
		}

		if (StrUtil.isNotBlank(kw)) {
			params.add(kw);
			params.add(kw);
			params.add(kw);
			params.add(kw);
			params.add(kw);
			params.add(kw);
			bufferSql.append(" AND (a.buy_mark like '%?%' ")
					 .append(" OR a.buyer like '% ").append("?").append("%'")
					 .append(" OR a.nick_name like '% ").append("?").append("%'")
					 .append(" OR a.wangwangid like '% ").append("?").append("%'")
					 .append(" OR a.taobao_order like '% ").append("?").append("%'")
					 .append(" OR a.express_number like '%?%' )");
		}

		Map<String, Object> retMap = this.jdbcTemplate.queryForMap(bufferSql.toString(), params.toArray());
		AnalysisVO ret = new AnalysisVO();
		ret.setCommissionFeeCnt(retMap.get("commissionFeeCnt").toString());
		ret.setExpressFeeCnt(retMap.get("expressFeeCnt").toString());
		ret.setPrincipalFeeCnt(retMap.get("principalFeeCnt").toString());
		ret.setSellFeeCnt(retMap.get("sellFeeCnt").toString());
		ret.setSellNumCnt(retMap.get("sellNumCnt").toString());
		return ret;
	}
}
